package com.example.qihuibao.module.service

import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.*
import com.example.qihuibao.bean.*
import com.example.qihuibao.constant.Config
import com.example.qihuibao.constant.Global
import com.example.qihuibao.network.RetrofitManager
import com.example.qihuibao.network.RetrofitModel
import com.example.qihuibao.utils.ConnectUtil
import com.example.qihuibao.utils.DES3Util
import com.example.qihuibao.utils.LogUtil
import com.google.gson.Gson
import com.koushikdutta.async.AsyncNetworkSocket
import com.koushikdutta.async.http.AsyncHttpClient
import com.koushikdutta.async.http.WebSocket
import com.koushikdutta.async.http.server.AsyncHttpServer
import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.lang.ref.WeakReference
import java.util.concurrent.ConcurrentHashMap


/**
 * 设备的侦听&连接
 */
class SocketService : Service() {
    private var threadRunning = true
    private var myHandler:MyHandler? = null
    private var callback:CallBack? = null
    private var connectStationCountdown = 3
    private var connectNetworkCountdown = 3
//    private var connectStation = false
//    private var connectICBC = true
    private var heartbeatCount = 0
    private var hasSendOfflineNotify = false
    private val stationRspMap = HashMap<String, ClientRsp>()

    override fun onCreate() {
        super.onCreate()
        myHandler = MyHandler(this)
        startGroupListener()
        startTimer()
        if (Config.isStation) {
            startStation()
        }
        ConnectUtil.groupSend()//启动时无论服务站或终端都发送一次组播，目的是(终端)获得服务站的ip或(服务站)广播ip给所有的终端
//        myHandler?.post { callback?.onEvent(EventType.SEND_GROUP, "") }//todo for test
    }

    override fun onDestroy() {
        super.onDestroy()
        threadRunning = false
    }

    override fun onBind(intent: Intent?): IBinder? {
        return MyBinder()
    }

    //侦听组播
    private fun startGroupListener() {
        Thread {
            while (threadRunning) {
                ConnectUtil.groupReceive {
                    if (it != null) {
                        getMultiCast(it)
//                        myHandler?.post { callback?.onEvent(EventType.RECEIVE_GROUP, it) }//todo for test
                    }
                }
            }
        }.start()
    }

    private fun startTimer() {
        Thread {
            while (threadRunning) {
                Thread.sleep(1000)
                if (!Config.isStation) {//client
                    if (connectStationCountdown > 0) {
                        if (--connectStationCountdown == 0) {
                            connectStationCountdown = 10
                            in10sTask()
                        }
                    }
                }
                if (connectNetworkCountdown > 0) {
                    if (--connectNetworkCountdown == 0) {
                        connectNetworkCountdown = 60
                        in60sTask()
                    }
                }
            }
        }.start()
    }

    //处理组播
    private fun getMultiCast(message: String) {
        val devBean = Gson().fromJson(message, DeviceBean::class.java)
        if (devBean != null) {
            if (devBean.ip != Global.devIp) {
                if (devBean.isServer) {//from server
                    if (devBean.targetIp.isEmpty() || devBean.targetIp == Global.devIp) {//empty时服务站群发，有目标ip的为发给指定设备
                        if (Config.isStation) { //原来是服务站的设备进入终端模式
                            stopStation()
                            Config.isStation = false
                        }
                        //终端处理
                        if (Config.stationIp != devBean.ip) {
                            Config.stationIp = devBean.ip
                        }
                        startConnectStation()
                    }else {
                        //服务站发给其它终端的，不处理
                    }
                }else {//from client
                    if (Config.isStation) {
                        ConnectUtil.groupSend(devBean.ip)//发送一次组播，目的是告诉client我的IP(终端获取不到station的IP时会定时发送一次组播等待station回应)
//                        myHandler?.post { callback?.onEvent(EventType.SEND_GROUP, devBean.ip) }//todo for test
                    }else {
                        //终端之间不处理
                    }
                }
            }else {
                //自身发出的，不处理
            }
        }else {
            LogUtil.e("解析组播数据异常")
        }
    }

    fun setCallback(callBack: CallBack) {
        this.callback = callBack
    }

    inner class MyBinder : Binder() {
        fun getService(): SocketService {
            return this@SocketService
        }
    }



    private var httpServer: AsyncHttpServer? = null
    private val webSockets = ConcurrentHashMap<String, WebSocket>()

    //启动本地服务
    fun startStation() {
        stopStation()
        httpServer = AsyncHttpServer()
        httpServer?.websocket("/", "") { webSocket, request ->
            if (webSocket != null) {
                val socketNum = webSockets.size
                webSockets[(webSocket.socket as AsyncNetworkSocket).remoteAddress.hostName] = webSocket //add socket
                if (socketNum != webSockets.size) {
                    myHandler?.post { callback?.onEvent(EventType.CONNECT_FROM_CLIENT, (webSocket.socket as AsyncNetworkSocket).remoteAddress.hostName) }
                }
                webSocket.setClosedCallback {
                    webSockets.remove((webSocket.socket as AsyncNetworkSocket).remoteAddress.hostName)
                    myHandler?.post { callback?.onEvent(EventType.CLIENT_CLOSE, (webSocket.socket as AsyncNetworkSocket).remoteAddress.hostName) }
                }
                webSocket.setStringCallback {
                    pushClientData((webSocket.socket as AsyncNetworkSocket).remoteAddress.hostName, it)
                }
            }
        }
        httpServer?.listen(Config.stationPort)
//        httpServer?.errorCallback = CompletedCallback { ex ->
//            if (ex != null) {
//            }
//        }
    }

    fun stopStation() {
        if (webSockets.isNotEmpty()) {
            for (item in webSockets) {
                item.value.close()
            }
            webSockets.clear()
        }
        httpServer?.stop()
        httpServer = null
    }

    private var clientWebSocket: WebSocket? = null
    //tcp connect server
    private fun startConnectStation() {
        if (Global.connectStation) {
            Global.connectStation = false
            stopConnectStation()
        }
        val url = "ws://${Config.stationIp}:${Config.stationPort}"
        AsyncHttpClient.getDefaultInstance().websocket(url, "") { ex, webSocket ->
            if (ex != null) {
                myHandler?.post { callback?.onEvent(EventType.CONNECT_STATION, "${ex.message}") }
                Global.connectStation = false
                return@websocket
            }
            if (webSocket != null) {
                Global.connectStation = true
                myHandler?.post { callback?.onEvent(EventType.CONNECT_STATION, "success") }
                webSocket.setClosedCallback {
                    myHandler?.post { callback?.onEvent(EventType.STATION_CLOSE, "close") }
                    Global.connectStation = false
                }
                webSocket.setStringCallback {
                    heartbeatCount = 0
                    pushStationData(it)
                }
            }
            clientWebSocket = webSocket
        }
    }

    fun stopConnectStation() {
        clientWebSocket?.closedCallback = null
        clientWebSocket?.close()
        clientWebSocket = null
        Global.connectStation = false
    }

    /**
     * 将终端发送给服务站的数据入队列
     */
    fun pushReqToStation(type:String, s:String, back:((type:String, rsp:String)->Unit)) {
        stationRspMap[type] = ClientRsp(back)
        val message = Message()
        message.what = 1
        val data = Bundle()
        data.putString("data", s)
        message.data = data
        myHandler?.sendMessage(message)
    }

    /**
     * （服务站）将接收到终端的数据入队列
     * hostName：找到对应的socket
     * s：终端数据
     */
    private fun pushClientData(hostName:String, s:String) {
        LogUtil.e("connectservice: pushClientData-$hostName, $s")
        val message = Message()
        message.what = 2
        val data = Bundle()
        data.putString("data", s)
        data.putString("hostName", hostName)
        message.data = data
        myHandler?.sendMessage(message)
    }

    /**
     * （服务站）处理接收到的终端的数据
     */
    private fun handleClientData(hostName:String, data:String) {
        val webSocket = webSockets[hostName]
        if (webSocket != null) {
            if (data == Global.SOCKET_HEARTBEAT_SEND) {//心跳
                sendData(webSocket, Global.SOCKET_HEARTBEAT_RECEIVE)
            }else if (data.startsWith(Global.CLIENT_REQ_HEAD)) {//终端的请求
                val s = data.replace(Global.CLIENT_REQ_HEAD, "")
                myHandler?.post { callback?.onEvent(EventType.REQ_FROM_CLIENT, ClientReq(webSocket, s)) }
            }
        }
    }

    /**
     * （终端）将接收到服务站的数据入队列
     */
    private fun pushStationData(s:String) {
        LogUtil.e("connectservice: pushStationData-$s")
        val message = Message()
        message.what = 3
        val data = Bundle()
        data.putString("data", s)
        message.data = data
        myHandler?.sendMessage(message)
    }

    /**
     * （终端）处理接收到的服务站的数据
     */
    private fun handleStationData(s:String) {
        if (s.startsWith(Global.STATION_RSP_HEAD)) {
            val rsp = s.replace(Global.STATION_RSP_HEAD, "")
            val sp = rsp.split("###")
            if (sp.size > 1) {
                stationRspMap[sp[0]]?.back?.invoke(sp[0], sp[1])
            }
        }
    }

    /**
     * （终端）发送数据到服务站
     */
    fun sendData2Station(data: String) {
        if (clientWebSocket != null && Global.connectStation) {
            sendData(clientWebSocket, data)
        }
    }

    fun isConnectStation(): Boolean {
        return Global.connectStation
    }

    fun getConnectList() : ConcurrentHashMap<String, WebSocket> {
        return webSockets
    }

    fun isConnectICBC(): Boolean {
        return Global.connectICBC
    }

    fun sendDataToAllClients(data:String) {
        if (!hasSendOfflineNotify) {
            hasSendOfflineNotify = true
            for (item in webSockets) {
                sendData(item.value, data)
            }
        }
    }

    fun sendData(webSocket: WebSocket?, data: String) {
        webSocket?.send(data)
        LogUtil.e("connectservice: ${if (Config.isStation) "服务站" else "终端"} sendData-$data")
    }

    private fun in10sTask() {
        if (!Global.connectStation) {
            ConnectUtil.groupSend()//发送一次组播进行侦听服务站回应
//            myHandler?.post { callback?.onEvent(EventType.SEND_GROUP, "") }//todo for test
        }else {//发送tcp心跳，保持终端和服务站的连接
            if (heartbeatCount < 3) {
                pushReqToStation("HEARTBEAT", Global.SOCKET_HEARTBEAT_SEND, { _, _->})
                heartbeatCount++
            }else {
                stopConnectStation()
                Global.connectStation = false
                heartbeatCount = 0
            }
        }
    }

    private fun in60sTask() {
        //todo 向工行服务器发送报文报告联网状态，并根据反馈报文的自动调整心跳频率
        val req = ReqHeartbeatBean()
        val body = ReqBean(DES3Util.EncryptData(Gson().toJson(req), Global.CorpKey), Global.CorpID)//加密请求数据
        RetrofitManager.getInstance().httpApi.post(body)?.enqueue(object : Callback<ResponseBody>{
            override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
//                val data = response.body()?.string()
//                val retData = DES3Util.DecryptData(data, Global.CorpKey)//解密响应数据
//                if (!retData.isNullOrEmpty()) {
//                    try {
//                        val retBean = RetrofitModel.parse<RspHeartbeatBean>(retData)
//                        if (retBean != null) {
//                            Global.connectICBC = true
//                            connectNetworkCountdown = retBean.Interval?.toInt()?:Global._60S
//                        }
//                    }catch (e:Exception) {
//                        Global.connectICBC = false
//                    }
//                }else {
//                    Global.connectICBC = true//todo true for test
//                }
                val rsp = response.body()?.string() ?: return
                val rspData = Global.gson.fromJson(rsp, Rspdata::class.java) ?: return
                val encryptData = rspData.repdata.replace("\n", "")//这是一个坑
                val realData = DES3Util.DecryptData(encryptData, Global.CorpKey)
                val retBean = RetrofitModel.parse<RspHeartbeatBean>(realData)
                if (retBean != null) {
                    Global.connectICBC = true
                    connectNetworkCountdown = try {
                        retBean.Interval?.toInt()?:Global._60S
                    }catch (e:Exception) {
                        Global._60S
                    }
                }else {
                    Global.connectICBC = false
                }
            }

            override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
                Global.connectICBC = false
                connectNetworkCountdown = 5
                if (!Config.deviceInit) {
                    Global.connectICBC = true
                    connectNetworkCountdown = Global._60S
                }
            }
        })
    }

//    private fun needShowDialog() {
//        if (Global.workMode == 1) {//已是离线模式
//            return
//        }
//        if (Config.isServerStation) {
//            if (!Global.connectICBC) {
//                showAlarmDialog()
//            }
//        }else {
//            if (!Global.connectICBC && !connectStation) {
//                showAlarmDialog()
//            }
//        }
//    }


    //service 弹窗需要开启悬浮功能
//    private fun showAlarmDialog() {
//        if (alarmDialog?.isShowing == true) {
//            return
//        }
//        if (alarmDialog == null) {
//            alarmDialog = AlertDialog.Builder(this, R.style.Theme_AppCompat).create()
//            alarmDialog?.setCancelable(false) // 设置点击dialog以外区域不取消Dialog
//            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//                alarmDialog?.getWindow()?.setType(WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY)
//            } else {
//                alarmDialog?.getWindow()?.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
//            }
//        }
//        alarmDialog?.show()
//        val view = View.inflate(this, R.layout.dialog_yes_or_no, null)
//        alarmDialog?.setContentView(view)
//        alarmDialog?.getWindow()?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
//        view.findViewById<TextView>(R.id.tv_message).text = "asfsfhsdafjadshfkajsdfh"
//        view.findViewById<View>(R.id.btn_cancel).setOnClickListener {
//            alarmDialog?.dismiss()
//        }
//        view.findViewById<View>(R.id.btn_ok).setOnClickListener {
//            alarmDialog?.dismiss()
//            Global.workMode = 1
//        }
//    }
//
//    private fun hideAlarmDialog() {
//        alarmDialog?.dismiss()
//        alarmDialog = null
//        Global.workMode = 0
//    }


    /**
     * handler 用于切换主线程
     */
    internal class MyHandler(ctx: Context) : Handler() {
        var weakReference: WeakReference<Context> = WeakReference(ctx)
        var socketService: SocketService? = null
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            //通过弱引用获取activity实例
            socketService = weakReference.get() as SocketService?
            if (socketService != null) {
                when (msg.what) {
                    1 -> socketService?.sendData2Station(msg.data.getString("data", ""))
                    2 -> {
                        val hostName = msg.data.getString("hostName", "")
                        val data = msg.data.getString("data", "")
                        socketService?.handleClientData(hostName, data)
                    }
                    3 -> socketService?.handleStationData(msg.data.getString("data", ""))
                }
            }
        }
    }

    interface CallBack {
        fun onEvent(eventType:EventType, data:Any?)
    }

    enum class EventType {
        CONNECT_STATION,
        STATION_CLOSE,
        RECEIVE_FROM_STATION,
        SEND_GROUP,
        RECEIVE_GROUP,
        CONNECT_FROM_CLIENT,
        CLIENT_CLOSE,
        REQ_FROM_CLIENT,
        RSP_TO_CLIENT,
        SEND_TO_STATION,
    }

    data class ClientReq(val webSocket: WebSocket, val data:String)

    data class ClientRsp(val back:(type:String, rsp:String)->Unit)

}